﻿using CourseClient;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Xml;
using VoteManager;

namespace MicroTest
{
    public partial class FrmVote : Form
    {
        private Dictionary<string, string> BindList;
        private Dictionary<string, CardManager> VoteManagerList;
        private Dictionary<string, VotePoint> VotePoints;
        private Graphics Graphic;
        private bool IsVoting = false;
        class VotePoint
        {
            public Point Point;
            public string PageSerial;
        }
        class VoteResultRect
        {
            public int PointX;
            public int PointY;
            public int Axis = 0;
            public int Wdith;
            public int Height;
            public int DelaHeight;
            public List<string> PenSerial = new List<string>();
            public bool GetVoteList(int x, int y, ref List<string> vote)
            {
                if (Height == 0)
                    return false;
                Debug.WriteLine(string.Format("[{0},{1}]  [{2},{3}]  [{4},{5}]", x, y, PointX, PointY, PointX + Wdith, PointY + Height));
                if (x >= PointX && x <= PointX + Wdith
                    && y >= PointY && y <= PointY + Height)
                {
                    vote.AddRange(PenSerial);
                    return true;
                }
                return false;
            }
        }
        VoteResultRect[] VoteResultList;
        public FrmVote(Dictionary<string, string> bl)
        {
            VoteManagerList = new Dictionary<string, CardManager>();
            BindList = bl;
            VotePoints = new Dictionary<string, VotePoint>();
            LoadVoteConfig("default.xml");
            VoteResultList = new VoteResultRect[5];
            for (int i = 0; i < 5; i++)
            {
                VoteResultRect vr = new VoteResultRect();
                vr.PointX = (150 + i * 150)/3;
                vr.Wdith = 50/3;
                vr.Height = 0;
                vr.PointY = 0;
                vr.Axis = 600/3;
                vr.DelaHeight = 500 / BindList.Count/3;
                VoteResultList[i] = vr;
            }
            InitializeComponent();
            // this.WindowState = FormWindowState.Maximized;

        }
        private void LoadVoteConfig(string configFile)
        {
            XmlDocument xmldoc = new XmlDocument();
            xmldoc.Load(configFile);
            XmlNodeList topM = xmldoc.DocumentElement.ChildNodes;
            foreach (XmlNode element in topM)
            {
                //Debug.WriteLine(element.Name + "  " + element.Attributes["PageAddress"]);
                if (element.Name == "OMRInfo" && element.Attributes["PageAddress"].Value == "1536.666.3.2")
                {
                    CardManager cardManager = new CardManager();
                    VoteManagerList.Add("1536.666.3.2", cardManager);
                    XmlNodeList innerList = element.ChildNodes;
                    foreach (XmlElement item in innerList)
                    {
                        if (item.Name == "Margin")
                        {
                            int marginX = (int)Convert.ToDouble(item.GetAttribute("x"));
                            int marginY = (int)Convert.ToDouble(item.GetAttribute("y"));
                            cardManager.SetMargin(marginX, marginY);
                        }
                        else if (item.Name == "CommandArea")
                        {
                            XmlNodeList comandNodeList = item.ChildNodes;
                            foreach (XmlElement comandNodeItem in comandNodeList)
                            {
                                string actionType = comandNodeItem.GetAttribute("action");
                                int x = (int)Convert.ToDouble(comandNodeItem.GetAttribute("x"));
                                int y = (int)Convert.ToDouble(comandNodeItem.GetAttribute("y"));
                                int w = (int)Convert.ToDouble(comandNodeItem.GetAttribute("width"));
                                int h = (int)Convert.ToDouble(comandNodeItem.GetAttribute("height"));
                                CommandArea command = new CommandArea(actionType, x, y, w, h);
                                cardManager.AddCommandArea(command);
                            }
                        }
                        else if (item.Name == "QuestionSize")
                        {
                            XmlNodeList sizeNodeList = item.ChildNodes;
                            foreach (XmlNode sizeNodeItem in sizeNodeList)
                            {

                                int w = (int)Convert.ToDouble(sizeNodeItem.Attributes["width"].Value);
                                int h = (int)Convert.ToDouble(sizeNodeItem.Attributes["height"].Value);
                                int gap = (int)Convert.ToDouble(sizeNodeItem.Attributes["gap"].Value);
                                int id = (int)Convert.ToDouble(sizeNodeItem.Attributes["id"].Value);
                                QuestionSize qs = new QuestionSize(id, w, h, gap);
                                cardManager.AddQuestionSize(qs);
                            }
                        }
                        else if (item.Name == "QuestionInfo")
                        {
                            XmlNodeList questionNodeList = item.ChildNodes;
                            foreach (XmlNode questionNodeItem in questionNodeList)
                            {
                                if (questionNodeItem is XmlComment)
                                    continue;
                                int no = (int)Convert.ToDouble(questionNodeItem.Attributes["no"].Value);
                                int sizeType = (int)Convert.ToDouble(questionNodeItem.Attributes["areasize"].Value);
                                int num = (int)Convert.ToDouble(questionNodeItem.Attributes["num"].Value);
                                int x = (int)Convert.ToDouble(questionNodeItem.Attributes["x"].Value);
                                int y = (int)Convert.ToDouble(questionNodeItem.Attributes["y"].Value);

                                cardManager.AddQuestion(no, sizeType, num, x, y);
                            }
                        }
                    }
                }
            }
        }
        public void DigitalPen_PenDown(ulong time, string penSerial, int penType)
        {

            if (!IsVoting || !BindList.ContainsKey(penSerial))
                return;
        }
        public void DigitalPen_PenUp(ulong time, string penSerial, int penType)
        {
            if (!IsVoting || !BindList.ContainsKey(penSerial))
                return;
            if (VotePoints.ContainsKey(penSerial))
            {
                HandleVotePoint(VotePoints[penSerial], penSerial);
            }
        }
        public void DigitalPen_PenCoordinate(ulong time, string penSerial, int penType, string pageSerial, ulong pageId, int cx, int cy, byte force)
        {
            if (!IsVoting || !BindList.ContainsKey(penSerial))
                return;
            if (!VoteManagerList.ContainsKey(pageSerial))
                return;
            if (!VotePoints.ContainsKey(penSerial))
            {
                VotePoint vp = new VotePoint();
                vp.Point = new Point(cx, cy);
                vp.PageSerial = pageSerial;
                VotePoints.Add(penSerial, vp);

            }
            else
            {
                VotePoints[penSerial].PageSerial = pageSerial;
                VotePoints[penSerial].Point.X = cx;
                VotePoints[penSerial].Point.Y = cy;

            }
        }
        private void HandleVotePoint(VotePoint vp, string penSerial)
        {
            CardManager cm = VoteManagerList[vp.PageSerial];

            int index = 0;
            Question qs = cm.GetQuestion(vp.Point.X, vp.Point.Y, ref index);
            if (qs != null && qs.ChoiceCount == 5)
            {
                if (Program.RemoteClass)
                {
                    StudentCard card = Program.CurrentClassInfo.GetStudentCardByName(BindList[penSerial]);
                    if (card != null)
                    {
                        VoteMessage msg = new VoteMessage(qs, index, card.StudentID);
                        DTClient.GetInstance().PutVoteMessage(msg);
                    }
                }
                bool NeedChange = false;
                int changeIndexFirst = 0, changeIndexLast = 0;
                for (int i = 0; i < 5; i++)
                {
                    if (VoteResultList[i].PenSerial.Contains(penSerial))
                    {
                        VoteResultList[i].PenSerial.Remove(penSerial);
                        changeIndexFirst = i;
                        NeedChange = true;
                        break;
                    }
                }
                if (NeedChange)
                {
                    VoteResultList[index].PenSerial.Add(penSerial);
                    if (changeIndexFirst != index)
                    {

                        changeIndexLast = index;
                        DrawVoteResult(new int[] { changeIndexFirst, changeIndexLast });
                    }

                }
                else
                {
                    VoteResultList[index].PenSerial.Add(penSerial);
                    changeIndexLast = index;
                    DrawVoteResult(new int[] { changeIndexLast });
                }
            }
            CommandArea command = cm.GetCommand(vp.Point.X, vp.Point.Y);
            if (command != null)
            {
                if (Program.RemoteClass)
                {
                    StudentCard card = Program.CurrentClassInfo.GetStudentCardByName(BindList[penSerial]);
                    if (card != null)
                    {
                        VoteMessage msg = new VoteMessage(command, card.StudentID);
                        DTClient.GetInstance().PutVoteMessage(msg);
                    }
                }
                bool NeedChange = false;
                int changeIndex = 0;
                for (int i = 0; i < 5; i++)
                {
                    if (VoteResultList[i].PenSerial.Contains(penSerial))
                    {
                        VoteResultList[i].PenSerial.Remove(penSerial);
                        changeIndex = i;
                        NeedChange = true;
                        break;
                    }
                }
                if (NeedChange)
                {
                    DrawVoteResult(new int[] { changeIndex });
                }
            }
        }

        private void DrawVoteResult(int[] questionIndex)
        {
            for (int i = 0; i < questionIndex.Length; i++)
            {
                VoteResultRect vr = VoteResultList[questionIndex[i]];
                vr.Height = (vr.DelaHeight*5);// * vr.PenSerial.Count;
                vr.PointY = (vr.Axis - vr.Height);
                //清空
                // Graphic.CompositingMode = System.Drawing.Drawing2D.CompositingMode.SourceCopy;

                //Bitmap tmp = new Bitmap(50, 500);
                //Graphic.DrawImage(tmp, vr.PointX,50, 50, 550);
                //Graphic.CompositingMode = System.Drawing.Drawing2D.CompositingMode.SourceOver;
                //Graphic.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighQuality;
                Graphic.FillRectangle(Brushes.White, vr.PointX, 50/3, 50/3, 550/3);

                //画新的
                if (vr.Height != 0)
                {
                    Graphic.DrawRectangle(new Pen(Brushes.Black, 1), vr.PointX, vr.PointY, 50/3, vr.Height);
                    Color clr = Color.FromArgb(84, 179, 228);
                    Brush brush = new SolidBrush(clr);
                    Graphic.FillRectangle(brush, vr.PointX, vr.PointY, 50/3, vr.Height);
                    int count = 5;//vr.PenSerial.Count;
                    Font font = new Font("Microsoft YaHei", 12);
                    SizeF sizeA = Graphic.MeasureString(count.ToString(), font);
                    int Ax = (int)(vr.PointX + 8 - sizeA.Width / 2);
                    Graphic.DrawString(count.ToString(), font, Brushes.Black, Ax, (vr.PointY - sizeA.Height - 10));

                }
                picVote.Invalidate(new Rectangle(vr.PointX, 50, 50, 550));
                picVote_2.Invalidate(new Rectangle(vr.PointX, 50, 50, 550));

            }
            if (LastTipQuestionIndex != -1)
            {
                this.BeginInvoke(new Action(() => {
                    toolTipAnswer.Hide(picVote);
                    LastTipQuestionIndex = -1;
                }));
            }


        }
        private void InitVoteResult()
        {
            Bitmap bitmap = new Bitmap(950/3, 700/3);
            Graphic = Graphics.FromImage(bitmap);

            Pen pen = new Pen(new SolidBrush(Color.Black), 1);
            //Graphic.DrawRectangle(pen, 0, 0, 899, 699);
            Graphic.FillRectangle(Brushes.White, 0, 0, 950/3, 650/3);

            Graphic.DrawLines(pen, new Point[]
            {
                new Point(50/3,50/3),
                new Point(50/3,600/3),
                new Point(900/3,600/3)
            });
            int choiceY = 610/3;
            int choiceX = 175/3;

            Font font = new Font("Microsoft YaHei", 12);

            SizeF sizeA = Graphic.MeasureString("A", font);
            int Ax = (int)(choiceX - sizeA.Width / 2);
            Graphic.DrawString("A", font, Brushes.Black, Ax, choiceY);
            choiceX += 150/3;

            SizeF sizeB = Graphic.MeasureString("B", font);
            int Bx = (int)(choiceX - sizeB.Width / 2);
            Graphic.DrawString("B", font, Brushes.Black, Bx, choiceY);
            choiceX += 150/3;

            SizeF sizeC = Graphic.MeasureString("C", font);
            int Cx = (int)(choiceX - sizeC.Width / 2);
            Graphic.DrawString("C", font, Brushes.Black, Cx, choiceY);
            choiceX += 150/3;

            SizeF sizeD = Graphic.MeasureString("D", font);
            int Dx = (int)(choiceX - sizeD.Width / 2);
            Graphic.DrawString("D", font, Brushes.Black, Dx, choiceY);
            choiceX += 150/3;

            SizeF sizeE = Graphic.MeasureString("E", font);
            int Ex = (int)(choiceX - sizeE.Width / 2);
            Graphic.DrawString("E", font, Brushes.Black, Ex, choiceY);
            choiceX += 150/3;
            picVote.Image = bitmap;
            picVote_2.Image = bitmap;
        }
        private void FrmVote_Load(object sender, EventArgs e)
        {
            picVote.Width = 950/3;         
            picVote.Left = (picVote.Parent.Width - picVote.Width) / 2/3;
            pnlButton.Left = (picVote.Left + 100)/3;
            InitVoteResult();

            btnEndVote.Enabled = false;
        }

        private void btnExit_Click(object sender, EventArgs e)
        {

            if (IsVoting)
            {
                if (Program.RemoteClass)
                {

                    VoteMessage msg = new VoteMessage(VoteDataActionType.BeginVote);
                    DTClient.GetInstance().PutVoteMessage(msg);
                }
            }
            IsVoting = false;
            btnStartVote.Enabled = true;
            btnEndVote.Enabled = false;
            this.Close();
        }
        private int LastTipQuestionIndex = -1;
        private void picVote_MouseMove(object sender, MouseEventArgs e)
        {
            bool found = false;
            int questionIndex = -1;
            //Point p=picVote.PointToClient(new Point(e.X, e.Y));
            List<string> list = new List<string>();
            for (int i = 0; i < 5; i++)
            {
                if (VoteResultList[i].GetVoteList(e.X, e.Y, ref list))
                {
                    found = true;
                    questionIndex = i;
                    break;
                }
            }
            if (found)
            {
                if (LastTipQuestionIndex != questionIndex)
                {
                    StringBuilder sb = new StringBuilder();
                    int index = 0;
                    foreach (var item in list)
                    {
                        sb.Append(BindList[item]);

                        if (index % 2 == 0)
                            sb.Append("\t");
                        else
                            sb.Append(Environment.NewLine);
                        index++;
                    }
                    toolTipAnswer.Show(sb.ToString(), picVote, e.X, e.Y);

                    LastTipQuestionIndex = questionIndex;
                }

            }
            else
            {
                if (LastTipQuestionIndex != -1)
                    toolTipAnswer.Hide(picVote);
                LastTipQuestionIndex = -1;

            }
        }

        private void btnStartVote_Click(object sender, EventArgs e)
        {
            IsVoting = true;
            VoteResultList = new VoteResultRect[5];
            for (int i = 0; i < 5; i++)
            {
                VoteResultRect vr = new VoteResultRect();
                vr.PointX = (150 + i * 150)/3;
                vr.Wdith = 50/3;
                vr.Height = 0;
                vr.PointY = 0;
                vr.Axis = 600/3;
                vr.DelaHeight = 500 / BindList.Count/3;
                VoteResultList[i] = vr;
            }
            InitVoteResult();
            btnStartVote.Enabled = false;
            btnEndVote.Enabled = true;
            if (Program.RemoteClass)
            {

                VoteMessage msg = new VoteMessage(VoteDataActionType.BeginVote);
                DTClient.GetInstance().PutVoteMessage(msg);
            }
        }

        private void btnEndVote_Click(object sender, EventArgs e)
        {
            IsVoting = false;
            btnEndVote.Enabled = false;
            btnStartVote.Enabled = true;
            if (Program.RemoteClass)
            {
                //模拟数据
                int[] nums = { 1,2,3};
                DrawVoteResult(nums);
                VoteMessage msg = new VoteMessage(VoteDataActionType.EndVote);
                DTClient.GetInstance().PutVoteMessage(msg);
            }
        }
        const int WM_NCLBUTTONDOWN = 0xA1;
        const int HT_CAPTION = 0x2;
        [System.Runtime.InteropServices.DllImport("user32.dll")]
        static extern int SendMessage(IntPtr hWnd, int Msg, int wParam, int lParam);

        // 窗体上鼠标按下时
        protected override void OnMouseDown(MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Left & this.WindowState == FormWindowState.Normal)
            {
                // 移动窗体
                this.Capture = false;
                SendMessage(Handle, WM_NCLBUTTONDOWN, HT_CAPTION, 0);
            }
        }
        private int LastMouseX, LastMouseY;

        private void pnlButton_MouseUp(object sender, MouseEventArgs e)
        {
            LastMouseX = 0;
            LastMouseY = 0;
        }

        private void pnlButton_MouseDown(object sender, MouseEventArgs e)
        {
            LastMouseX = MousePosition.X;
            LastMouseY = MousePosition.Y;
        }

        private void pnlButton_MouseMove(object sender, MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Left & this.WindowState == FormWindowState.Normal)
            {
                int delaX = MousePosition.X - LastMouseX;
                int delaY = MousePosition.Y - LastMouseY;
                this.Left += delaX;
                this.Top += delaY;
                LastMouseX = MousePosition.X;
                LastMouseY = MousePosition.Y;

            }
        }
    }
}
